﻿using System;
using System.Linq;
using System.Reflection;

namespace Flatland.GeneticProgramming {
    /// <summary>
    /// GPTechnique attribute.
    /// </summary>
    sealed class GPTechnique : Attribute {
        public Object Implementer { get; set; }
        public GPTechnique(Type technique) {
            Implementer = Activator.CreateInstance(technique);
        }

        /// <summary>
        /// Get the implementer of a GP Technique by its enum.
        /// </summary>
        /// <param name="t"></param>
        /// <param name="enumUid"></param>
        /// <returns></returns>
        public static Object GetImplementer(Type t, int enumUid) {
            foreach (FieldInfo fi in (from fi in t.GetFields(BindingFlags.Public | BindingFlags.Static)
                                      where ((int)fi.GetRawConstantValue() == enumUid) && IsDefined(fi, typeof(GPTechnique))
                                      select fi)) {
                return ((GPTechnique)GetCustomAttribute(fi, typeof(GPTechnique))).Implementer;
            }
            throw new Exception("GP Technique must be attributed with GPTechnique.");
        }
    }
}
